#!/usr/bin/env bash
#Checked with ShellCheck (https://www.shellcheck.net/)

#/ Kurento Module scaffolding tool.
#/
#/ This tool is used to create an initial project structure that can be used
#/ as the basis to develop a new Kurento module.
#/
#/
#/ Usage
#/ -----
#/
#/ kurento-module-scaffold <Prefix> <CamelCaseName> <snake_case_name> [IsOpenCV? true|false]
#/
#/
#/ Arguments
#/ ---------
#/
#/ <Prefix>
#/
#/   Prefix used for the new module, in UpperCamelCase (also known as PascalCase).
#/
#/   This should be an application- or library-specific namespace prefix in
#/   order to avoid name conflicts in case a similar plugin with the same name
#/   ever gets added to GStreamer.
#/
#/   If an empty string ("") is given, then "Gst" will be used by default.
#/
#/   Example: "App".
#/
#/   Required.
#/
#/ <CamelCaseName>
#/
#/   Name of the new module, in UpperCamelCase (also known as PascalCase).
#/
#/   Example: "OpenCVModule".
#/
#/   Required.
#/
#/ <snake_case_name>
#/
#/   Name of the new module, in snake_case.
#/
#/   This is used to give names to several files, and also to name the target
#/   directory where the autogenerated files will be placed.
#/
#/   Example: "opencv_module".
#/
#/   Required.
#/
#/ [IsOpenCV? true|false]
#/
#/   Set to "true" to indicate that an OpenCV module should be prepared.
#/   Otherwise, a GStreamer module will be prepared.
#/
#/   Optional. Default: "false".

# Bash options for strict error checking.
set -o errexit -o errtrace -o pipefail -o nounset
shopt -s inherit_errexit 2>/dev/null || true

# Trace all commands (to stderr).
#set -o xtrace

# Exit trap function.
# Runs always at the end, either on success or error (errexit).
function on_exit {
    { _RC=$?; set +o xtrace; } 2>/dev/null
    if ((_RC)); then echo "[$0] ERROR ($_RC)"; fi
}
trap on_exit EXIT

# Help message.
# Extracts and prints text from special comments in the script header.
function usage { grep '^#/' "${BASH_SOURCE[-1]}" | cut -c 4-; exit 0; }
if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then usage; fi
if [[ $# -lt 2 ]]; then usage; fi

# Parse arguments
prefixCamelCase="${1:-Gst}"
nameCamelCase="${2:-NewModule}"
nameSnakeCase="${3:-new_module}"
isOpenCV="${4:-false}"

# Sanity check
prefixCamelCase="$(echo "$prefixCamelCase" | tr --delete '[:blank:]_-')"
nameCamelCase="$(echo "$nameCamelCase" | tr --delete '[:blank:]_-')"
nameSnakeCase="$(echo "$nameSnakeCase" | tr --delete '[:blank:]')"
nameSnakeCase="$(echo "$nameSnakeCase" | tr '[:upper:]' '[:lower:]')"
nameSnakeCase="$(echo "$nameSnakeCase" | tr '-' '_')"

# Derive other forms of naming
prefixLowerCase="$(echo "$prefixCamelCase" | tr '[:upper:]' '[:lower:]')"
prefixUpperCase="$(echo "$prefixCamelCase" | tr '[:lower:]' '[:upper:]')"
nameLowercase="$(echo "$nameCamelCase" | tr '[:upper:]' '[:lower:]')"
nameKebabCase="$(echo "$nameSnakeCase" | tr '_' '-')"
nameSnakeUpperCase="$(echo "$nameSnakeCase" | tr '[:lower:]' '[:upper:]')"

# Extra template replacements
if [[ "$isOpenCV" == "true" ]]; then
    extendsFilter="OpenCVFilter"
else
    extendsFilter="Filter"
fi
debianDate="$(date -R)"
debianYear="$(date '+%Y')"
debianMaintainer="Maintainer Name <maintainer.name@example.com>"


function template_replace {
    local inPath="${1:-/tmp/nonexistent}"
    local outPath="${2:-/tmp/nonexistent}"

    sed \
        -e "s|{{prefixCamelCase}}|$prefixCamelCase|g" \
        -e "s|{{prefixLowerCase}}|$prefixLowerCase|g" \
        -e "s|{{prefixUpperCase}}|$prefixUpperCase|g" \
        -e "s|{{nameCamelCase}}|$nameCamelCase|g" \
        -e "s|{{nameSnakeCase}}|$nameSnakeCase|g" \
        -e "s|{{nameLowercase}}|$nameLowercase|g" \
        -e "s|{{nameKebabCase}}|$nameKebabCase|g" \
        -e "s|{{nameSnakeUpperCase}}|$nameSnakeUpperCase|g" \
        -e "s|{{extendsFilter}}|$extendsFilter|g" \
        -e "s|{{debianDate}}|$debianDate|g" \
        -e "s|{{debianYear}}|$debianYear|g" \
        -e "s|{{debianMaintainer}}|$debianMaintainer|g" \
        "$inPath" \
        >"$outPath"
}


outputDir="$nameKebabCase"
sourceDir="@CMAKE_INSTALL_PREFIX@/share/kurento/scaffold"

# Change to output directory
mkdir -p "$outputDir"
cd "$outputDir"

git init

# Create folder tree
mkdir src
pushd src >/dev/null

cat "$sourceDir/CMakeLists_server.txt.template" >CMakeLists.txt

if [[ "$isOpenCV" != "true" ]]; then
    mkdir gst-plugins
    cat "$sourceDir/CMakeLists_server_plugin.txt.template" >>CMakeLists.txt

    pushd gst-plugins >/dev/null

    template_replace "$sourceDir/CMakeLists_gstplugin.txt.template" CMakeLists.txt
    template_replace "$sourceDir/gstplugin.c.template" "$nameLowercase.c"
    template_replace "$sourceDir/gstplugin.h.template" "${prefixLowerCase}${nameLowercase}.h"
    template_replace "$sourceDir/gstplugin.cpp.template" "${prefixLowerCase}${nameLowercase}.cpp"

    popd >/dev/null # gst-plugins
fi

{
    mkdir server
    pushd server >/dev/null

    mkdir implementation

    {
        mkdir interface
        pushd interface >/dev/null

        template_replace "$sourceDir/filter.kmd.json.template" "${nameLowercase}.kmd.json"
        template_replace "$sourceDir/filter.Filter.kmd.json.template" "${nameLowercase}.${nameCamelCase}.kmd.json"

        popd >/dev/null # interface
    }

    cat "$sourceDir/CMakeLists_src.txt.template" >CMakeLists.txt

    popd >/dev/null # server
}

popd >/dev/null # src

if [[ "$isOpenCV" == "true" ]]; then
    template_replace "$sourceDir/CMakeLists_root.txt.opencv.template" CMakeLists.txt
else
    template_replace "$sourceDir/CMakeLists_root.txt.gstreamer.template" CMakeLists.txt
fi

template_replace "$sourceDir/config.h.cmake.template" config.h.cmake

# Create a "debian/" directory for creation of .deb package files
{
    mkdir debian
    pushd debian >/dev/null

    template_replace "$sourceDir/debian-copyright.template" copyright
    template_replace "$sourceDir/debian-changelog.template" changelog

    cat "$sourceDir/debian-rules.template" >rules

    if [[ "$isOpenCV" == "true" ]]; then
        template_replace "$sourceDir/debian-control.opencv.template" control
        cat "$sourceDir/debian-name.install.opencv.template" >"${nameKebabCase}.install"
    else
        template_replace "$sourceDir/debian-control.gstreamer.template" control
        cat "$sourceDir/debian-name.install.gstreamer.template" >"${nameKebabCase}.install"
    fi

    cat "$sourceDir/debian-name-dev.install.template" >"${nameKebabCase}-dev.install"

    mkdir source
    echo "3.0 (quilt)" >source/format

    popd >/dev/null # debian
}

tee .gitignore >/dev/null <<EOF
### Project ignores ###

# Build directories
build/
build-*/

# Debian packaging (debhelper)
debian/.debhelper/
debian/debhelper-build-stamp
debian/files
debian/${nameKebabCase}*.debhelper.log
debian/${nameKebabCase}*.substvars
debian/${nameKebabCase}/
debian/tmp/
kurento-*_*_amd64.buildinfo
kurento-*_*_amd64.changes
kurento-*_*.dsc
kurento-*_*.tar.xz
obj-x86_64-linux-gnu/
EOF

git add CMakeLists.txt src .gitignore config.h.cmake debian
git commit -m "Initial commit"

echo "Done! Scaffolding tree has been created."
echo
echo "Note that a sample Apache-2.0 license has been set by default;"
echo "you can change it in 'debian/copyright', and maybe adding a LICENSE file."
